package schedulo.gui.components;

import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.Dimension;
import java.awt.Graphics;
import java.awt.GridBagConstraints;
import java.awt.GridBagLayout;
import java.awt.Point;
import java.awt.Rectangle;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
import java.awt.event.MouseListener;
import java.awt.event.MouseMotionListener;

import javax.swing.JComponent;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.JScrollPane;
import javax.swing.JTable;

public class ScheduleTable extends JComponent {

	private ScheduleView scheduleView;

	private JPanel schedulePanel;

	private WeekSelector weekSelector;

	private JScrollPane scrollPane;

	public ScheduleTable() {

		scrollPane = new JScrollPane(getSchedulePanel());
		scrollPane
				.setHorizontalScrollBarPolicy(JScrollPane.HORIZONTAL_SCROLLBAR_ALWAYS);
		scrollPane
				.setVerticalScrollBarPolicy(JScrollPane.VERTICAL_SCROLLBAR_ALWAYS);

		setLayout(new GridBagLayout());
		GridBagConstraints gbc = new GridBagConstraints();
		gbc.anchor = GridBagConstraints.NORTHWEST;
		gbc.fill = GridBagConstraints.BOTH;
		gbc.weightx = 1.0;
		gbc.weighty = 1.0;
		add(scrollPane, gbc);
	}

	private JPanel getSchedulePanel() {
		if (schedulePanel == null) {
			schedulePanel = new JPanel();

			schedulePanel.setLayout(new BorderLayout());
			schedulePanel.add(getWeekSelector(), BorderLayout.NORTH);
			schedulePanel.add(getScheduleView(), BorderLayout.CENTER);

		}
		return schedulePanel;
	}

	private WeekSelector getWeekSelector() {
		if (weekSelector == null) {
			weekSelector = new WeekSelector();

		}
		return weekSelector;
	}

	private ScheduleView getScheduleView() {
		if (scheduleView == null) {
			scheduleView = new ScheduleView();

		}
		return scheduleView;
	}

	class ScheduleView extends JComponent {

		public static final int MINIMAL_HOUR_HEIGHT = 44; // 4* font 12

		public static final int MINIMAL_DAY_WIDTH = 75;

		private int hourHeight;

		private int dayWidth;

		private boolean mouseSelecting;

		private Point mouseOrigin;

		private Rectangle mouseSelection;

		public ScheduleView() {
			ScheduleViewMouseAdapter svma = new ScheduleViewMouseAdapter();
			addMouseListener(svma);
			addMouseMotionListener(svma);
		}

		public Dimension getMinimumSize() {
			return new Dimension(8 * MINIMAL_DAY_WIDTH,
					25 * MINIMAL_HOUR_HEIGHT);
		}

		public Dimension getPreferredSize() {
			Dimension minimumSize = getMinimumSize();
			Dimension preferredSize = super.getPreferredSize();
			if (minimumSize.width > preferredSize.width
					|| minimumSize.height > preferredSize.height) {
				return minimumSize;
			}
			return preferredSize;
		}

		class ScheduleViewMouseAdapter extends MouseAdapter {

			public void mousePressed(MouseEvent e) {
				mouseOrigin = e.getPoint();
			}

			public void mouseDragged(MouseEvent e) {
				if (mouseOrigin != null) {
					mouseSelecting = true;
					Point current = e.getPoint();

					int r_x = Math.min(current.x, mouseOrigin.x);
					int r_y = Math.min(current.y, mouseOrigin.y);

					int r_width = Math.max(current.x, mouseOrigin.x) - r_x;
					int r_height = Math.max(current.y, mouseOrigin.y) - r_y;

					mouseSelection = new Rectangle(r_x, r_y, r_width, r_height);
					repaint();
				}
			}

			public void mouseReleased(MouseEvent e) {
				mouseSelecting = false;
				mouseOrigin = null;
				mouseSelection = null;
			}
		}

		protected void paintComponent(Graphics g) {

			// round width
			int width = ((getWidth() - MINIMAL_DAY_WIDTH) / 7) * 7;

			// clear the surface
			g.clearRect(0, 0, getWidth(), getHeight());

			dayWidth = width / 7;
			hourHeight = getHeight() / 25; // one hour box use to display the
			// day header

			g.setColor(Color.GRAY);

			// days headers
			g.fillRect(MINIMAL_DAY_WIDTH, 0, width, hourHeight);

			// cell border
			for (int x = 0; x < 7; x++) {
				for (int y = 1; y < 25; y++) {
					Rectangle rect = new Rectangle(x * dayWidth
							+ MINIMAL_DAY_WIDTH, y * hourHeight,
							dayWidth, hourHeight);

					if (mouseSelecting && mouseSelection.intersects(rect)) {
						g.fillRect(rect.x, rect.y, rect.width, rect.height);
					}

					g.drawRect(rect.x, rect.y, rect.width, rect.height);
				}
			}

			// 1 column hour borders
			for (int y = 1; y < 25; y++) {
				g.drawRect(0, y * hourHeight, MINIMAL_DAY_WIDTH, (y + 1)
						* hourHeight);
			}
		}
	}

	class WeekSelector extends JLabel {
		public WeekSelector() {
			super("Week Selector");
			setHorizontalAlignment(JLabel.CENTER);
			setVerticalAlignment(JLabel.CENTER);

		}
	}

}
